﻿#include <Windows.h>
#include <tchar.h>

#include <iostream>

#include "device.h"

using namespace windows::user;


DWORD ThreadRoutine(LPVOID lpThreadParameter) {
  static DWORD thread_index = 0;
  DWORD index;
  DWORD result;
  WCHAR time_buffer[24];
  DWORD time_buffer_size;
  OVERLAPPED overlapped;
  Device *device = reinterpret_cast<Device*>(lpThreadParameter);

  time_buffer_size = sizeof(time_buffer);
  RtlZeroMemory(&overlapped, sizeof(overlapped));
  overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  if (overlapped.hEvent) {
    result = device->ReadAsync(time_buffer, time_buffer_size, overlapped);
    if (ERROR_SUCCESS != result && ERROR_IO_PENDING != result) {
      _tprintf(TEXT("device.Read fail, error=%d\n"), result);
    } else {
      index = thread_index;
      if (1 == thread_index++) {
        if (device->CancelIo()) {
          _tprintf(TEXT("thread_index=%d, CacenIo success\n"), index);
        } else {
          _tprintf(TEXT("thread_index=%d, CacenIo fail\n"), index);
        }
      }
      result = WaitForSingleObject(overlapped.hEvent, INFINITE);
      if (WAIT_OBJECT_0 == result) {
        _tprintf(TEXT("index=%d, time:%d,%s\n"), index, time_buffer_size, time_buffer);
      } else {
        _tprintf(TEXT("index=%d, WaitForSingleObject fail, error=%d\n"), index, result);
      }
    }
    CloseHandle(overlapped.hEvent);
  } else {
    _tprintf(TEXT("CreateEvent fail, error=%d\n"), GetLastError());
  }
  return 0;
}

#define THREAD_NUMBER 3
int main() {
  DWORD result;
  Device device;
  size_t thread_count;
  HANDLE thread_handle[THREAD_NUMBER];

  do {
    result = device.Open(TEXT("Asynchronous"), TRUE);
    if (ERROR_SUCCESS != result) {
      _tprintf(TEXT("main device.Open fail, Error=%d\n"), result);
      break;
    }
    _tprintf(TEXT("device.Open success\n"));
    for (thread_count = 0; thread_count < THREAD_NUMBER; ++thread_count) {
      thread_handle[thread_count] = CreateThread(NULL, 0, ThreadRoutine, &device, 0, NULL);
      if (!thread_handle[thread_count]) {
        _tprintf(TEXT("%llu CreateThread fail, error=%d\n"), thread_count, GetLastError());
        break;
      } else {
        _tprintf(TEXT("%llu CreateThread success, handle=%p\n"), thread_count, thread_handle[thread_count]);
      }
    }
    result = WaitForMultipleObjects(thread_count, thread_handle, TRUE, INFINITE);
    _tprintf(TEXT("WaitForMultipleObjects return %d\n"), result);
  } while (false);
  device.Close();
  return EXIT_SUCCESS;
}

